package com.rskj.cashbook.service.iml;

import com.rskj.cashbook.dao.CashBookDao;
import com.rskj.cashbook.service.ICashBookService;
import com.rskj.cashbook.util.DateUtil;
import com.rskj.cashbook.util.SnowflakeIdWorker;
import com.rskj.cashbook.vo.CashBook;
import com.rskj.cashbook.vo.Query.StatementsQueryVo;
import com.rskj.cashbook.vo.ReportDetailVo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class CashBookService implements ICashBookService {

    private final CashBookDao cashBookDao;
    private final UserInfoService userInfoService;

    @Override
    public int insert(CashBook cashBook) {
        cashBook.setId(SnowflakeIdWorker.getId());
        if (null == cashBook.getConsumerDate()) {
            cashBook.setConsumerDate(new Date());
        }
        
        // 设置时间相关字段
        cashBook.setQuarter(DateUtil.getQuarterOfYear(cashBook.getConsumerDate()))
                .setWeek(DateUtil.getWeekOfYear(cashBook.getConsumerDate()))
                .setMonth(DateUtil.getMonthOfYear(cashBook.getConsumerDate()))
                .setCreateBy(userInfoService.getCurrUsername());
        
        // 处理账单类型
        processBillType(cashBook);
        
        return cashBookDao.insert(cashBook);
    }

    /**
     * 处理账单类型和分类
     */
    private void processBillType(CashBook cashBook) {
        // 如果账单类型为空，设置默认值
        if (cashBook.getBillType() == null) {
            cashBook.setBillType("EXPENSE");
        }
        
        // 根据账单类型设置分类和收入标识
        switch (cashBook.getBillType()) {
            // 收入类型
            case "INCOME":
            case "SALARY":
            case "BONUS":
            case "INVESTMENT":
            case "REFUND":
            case "PART_TIME":
            case "BUSINESS":
            case "RENTAL":
            case "INTEREST":
            case "DIVIDEND":
            case "GIFT":
            case "OTHER_INCOME":
                cashBook.setBillCategory("INCOME");
                cashBook.setIsIncome(1);
                break;
            // 支出类型
            case "EXPENSE":
            case "FOOD":
            case "TRANSPORT":
            case "SHOPPING":
            case "ENTERTAINMENT":
            case "HOUSING":
            case "UTILITIES":
            case "MEDICAL":
            case "EDUCATION":
            case "INSURANCE":
            case "INVESTMENT_EXPENSE":
            case "OTHER_EXPENSE":
                cashBook.setBillCategory("EXPENSE");
                cashBook.setIsIncome(0);
                break;
            // 转账类型
            case "TRANSFER":
            case "TRANSFER_IN":
            case "TRANSFER_OUT":
                cashBook.setBillCategory("TRANSFER");
                cashBook.setIsIncome("TRANSFER_IN".equals(cashBook.getBillType()) ? 1 : 0);
                break;
            // 借贷类型
            case "LOAN":
            case "LEND":
            case "BORROW":
                cashBook.setBillCategory("LOAN");
                cashBook.setIsIncome("BORROW".equals(cashBook.getBillType()) ? 1 : 0);
                break;
            default:
                // 默认为支出
                cashBook.setBillCategory("EXPENSE");
                cashBook.setIsIncome(0);
                break;
        }
        
        // 设置账单类型名称
        cashBook.setBillTypeName(getBillTypeName(cashBook.getBillType()));
    }

    /**
     * 获取账单类型名称
     */
    private String getBillTypeName(String billType) {
        if (billType == null) {
            return "支出";
        }
        
        switch (billType) {
            // 收入类型
            case "INCOME": return "收入";
            case "SALARY": return "工资";
            case "BONUS": return "奖金";
            case "INVESTMENT": return "投资收益";
            case "REFUND": return "退款";
            case "PART_TIME": return "兼职收入";
            case "BUSINESS": return "经营收入";
            case "RENTAL": return "租金收入";
            case "INTEREST": return "利息收入";
            case "DIVIDEND": return "分红收入";
            case "GIFT": return "礼金收入";
            case "OTHER_INCOME": return "其他收入";
            // 支出类型
            case "EXPENSE": return "支出";
            case "FOOD": return "餐饮";
            case "TRANSPORT": return "交通";
            case "SHOPPING": return "购物";
            case "ENTERTAINMENT": return "娱乐";
            case "HOUSING": return "住房";
            case "UTILITIES": return "水电费";
            case "MEDICAL": return "医疗";
            case "EDUCATION": return "教育";
            case "INSURANCE": return "保险";
            case "INVESTMENT_EXPENSE": return "投资支出";
            case "OTHER_EXPENSE": return "其他支出";
            // 转账类型
            case "TRANSFER": return "转账";
            case "TRANSFER_IN": return "转入";
            case "TRANSFER_OUT": return "转出";
            // 借贷类型
            case "LOAN": return "借贷";
            case "LEND": return "借出";
            case "BORROW": return "借入";
            default: return "其他";
        }
    }

    @Override
    public List<CashBook> selectCashBook(CashBook cashBook) {
        return cashBookDao.selectCashBook((CashBook) cashBook
                .setCreateBy(userInfoService.getCurrUsername()));
    }

    @Override
    public List<CashBook> selectCashBookGroupByDate() {
        return cashBookDao.selectCashBookGroupByDate((CashBook) new CashBook()
                .setCreateBy(userInfoService
                        .getCurrUsername()));
    }

    public BigDecimal statements(StatementsQueryVo queryVo) {
        return cashBookDao.selectStatements((StatementsQueryVo) queryVo
                .setCreateBy(userInfoService.getCurrUsername()));
    }

    @Override
    public int updateCashBook(List<CashBook> cashBooks) {
        List<CashBook> updateList = cashBooks.stream()
                .filter(cashBook -> StringUtils.isNotEmpty(cashBook.getId()) && cashBook.getId() != null)
                .distinct().toList();
        
        if (updateList.isEmpty()) {
            return 0;
        }
        
        return cashBookDao.updateBatch(updateList);
    }

    @Override
    public List<ReportDetailVo> cashBookReport(StatementsQueryVo queryVo) {
        queryVo.setCreateBy(userInfoService.getCurrUsername());
        return cashBookDao.selectCashBookReport(queryVo);
    }

    /**
     * 获取账单统计信息
     */
    public Map<String, Object> getBillStatistics() {
        String currentUser = userInfoService.getCurrUsername();
        Map<String, Object> statistics = new HashMap<>();
        
        try {
            // 查询收入统计
            CashBook incomeQuery = new CashBook();
            incomeQuery.setCreateBy(currentUser);
            incomeQuery.setIsIncome(1);
            List<CashBook> incomeBills = cashBookDao.selectCashBook(incomeQuery);
            
            // 查询支出统计
            CashBook expenseQuery = new CashBook();
            expenseQuery.setCreateBy(currentUser);
            expenseQuery.setIsIncome(0);
            List<CashBook> expenseBills = cashBookDao.selectCashBook(expenseQuery);
            
            // 计算总收入
            BigDecimal totalIncome = incomeBills.stream()
                .map(CashBook::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 计算总支出
            BigDecimal totalExpense = expenseBills.stream()
                .map(CashBook::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 计算净收入
            BigDecimal netIncome = totalIncome.subtract(totalExpense);
            
            statistics.put("totalIncome", totalIncome.doubleValue());
            statistics.put("totalExpense", totalExpense.doubleValue());
            statistics.put("netIncome", netIncome.doubleValue());
            statistics.put("incomeCount", incomeBills.size());
            statistics.put("expenseCount", expenseBills.size());
            statistics.put("totalCount", incomeBills.size() + expenseBills.size());
            
            // 按账单类型统计
            Map<String, Double> incomeByType = incomeBills.stream()
                .collect(Collectors.groupingBy(
                    bill -> bill.getBillType() != null ? bill.getBillType() : "OTHER",
                    Collectors.reducing(0.0, 
                        bill -> bill.getAmount() != null ? bill.getAmount().doubleValue() : 0.0, 
                        Double::sum)
                ));
            
            Map<String, Double> expenseByType = expenseBills.stream()
                .collect(Collectors.groupingBy(
                    bill -> bill.getBillType() != null ? bill.getBillType() : "OTHER",
                    Collectors.reducing(0.0, 
                        bill -> bill.getAmount() != null ? bill.getAmount().doubleValue() : 0.0, 
                        Double::sum)
                ));
            
            statistics.put("incomeByType", incomeByType);
            statistics.put("expenseByType", expenseByType);
            
        } catch (Exception e) {
            // log.error("获取账单统计信息失败: {}", e.getMessage(), e);
            statistics.put("error", e.getMessage());
        }
        
        return statistics;
    }
}
